/*--------------------------------------------------------------------------------------------------
Yatak Operation System Project Copyright 2012-2013
Author : Ilya Churaev
Started : 25 Apr 2012		Updated : 1 May 2012
File Name : cmos.c		Purpose : get information from cmos
--------------------------------------------------------------------------------------------------*/
#include <yatak/port.h>
#include <screen.h>
#include <types.h>
#include <cmos.h>

int cmos_read(byte address)
{
	while(cmos_busy());
	outportb(CMOS_OUT_PORT, 0x80|address);			/* Use 0x80 coz we need to disable NMI */
	return bcd2bin(inportb(CMOS_IN_PORT));
}

bool cmos_busy()
{
	outportb(CMOS_OUT_PORT, 0x80|STATUS_A);
	if(inportb(CMOS_IN_PORT) & 0x80)			// Bit 7 is set in Status Register A if Clock is busy */
		return true;
	else
		return false;
}

int bcd2bin(byte bcd)
{
	return((bcd & 0xF) + ((bcd >> 4) * 10));
}

// Detect floppy drive
void detect_floppy_drives()
{
	unsigned char c;
	unsigned char a, b;
	char *drive_type[5] = {
		"no floppy drive",
		"360kb 5.25in floppy drive",
		"1.2mb 5.25in floppy drive",
		"720kb 3.5in",
		"1.44mb 3.5in",
		"2.88mb 3.5in" };

	outportb(0x70, 0x10);
	c = inportb(0x71);

	a = c >> 4; // get the high nibble
	b = c & 0xF; // get the low nibble by ANDing out the high nibble

	kprintf("Floppy drive A is an:\n%s\nFloppy drive B is an:\n%s\n",drive_type[a],drive_type[b]);
};

/* BCD to BIN Math
   Its easy to explain with an example
   Input : bin = 25 BCD
  		  bin = 0010 0101
  		  bin & 0xF = 0000 0101          -> (a)
  		  bin >> 4 = 0000 0010
  		  (bin >> 4) * 10 = 0001 0100    -> (b)
  		  (a) + (b) = 0001 1001 -> This is 25 in BINARY */
  		  
// Reading from the CMOS 		  
void ReadFromCMOS (unsigned char array [])
{
	unsigned char tvalue, index;
	for(index = 0; index < 128; index++)
	{
		/*
		asm {
			cli             // Disable interrupts
			mov al, index   // Move index address
			// since the 0x80 bit of al is not set, NMI is active 
			out 0x70,al     // Copy address to CMOS register
			// some kind of real delay here is probably best 
			in al,0x71      // Fetch 1 byte to al
			sti             // Enable interrupts
			mov tvalue,al
		}*/
		tvalue = cmos_read (index);
		array[index] = tvalue;
	}
}

// Writing to the CMOS
void WriteToCMOS(unsigned char array[])
{
	unsigned char index;
	for(index = 0; index < 128; index++)
	{
		unsigned char tvalue = array[index];
		/*
		_asm
		{
			cli             // Clear interrupts
			mov al,index    // move index address
			out 0x70,al     // copy address to CMOS register
			// some kind of real delay here is probably best 
			mov al,tvalue   // move value to al
			out 0x71,al     // write 1 byte to CMOS
			sti             // Enable interrupts
		}*/
		outportb(CMOS_OUT_PORT, index);
		outportb(CMOS_IN_PORT, tvalue);
	}
}
